"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const axios_1 = require("axios");
const CryptoJs = require("crypto-js");

// --- Constants ---
const pageSize = 50;
const API_BASE_URL = 'https://lrc.xms.mx';
const ALL_PLAYLISTS_TAG = {
  id: 'navidrome__all_playlists',
  title: '在线歌单'
};
// --- NEW: Tag object for browsing all songs ---
const ALL_SONGS_TAG = {
    id: 'navidrome__all_songs',
    title: '所有歌曲'
};

// --- Helper function for Navidrome API calls ---
async function httpGet(urlPath, params) {
    var _a;
    const userVariables = (_a = env === null || env === void 0 ? void 0 : env.getUserVariables()) !== null && _a !== void 0 ? _a : {};
    let { url, username, password } = userVariables;
    if (!(url && username && password)) {
        console.error("Navidrome Plugin: Missing URL, username, or password in settings.");
        throw new Error("请在插件设置中填写 Navidrome 服务器地址、用户名和密码");
    }
    if (!url.startsWith("http://") && !url.startsWith("https://")) url = `http://${url}`;
    url = url.replace(/\/+$/, "");
    const salt = Math.random().toString(16).slice(2);
    const token = CryptoJs.MD5(`${password}${salt}`).toString(CryptoJs.enc.Hex);
    const baseParams = { u: username, s: salt, t: token, c: "MusicFree", v: "1.16.1", f: "json" };
    const fullUrl = `${url}/rest/${urlPath}`;
    try {
        const response = await axios_1.default.get(fullUrl, { params: { ...baseParams, ...params }, timeout: 20000 });
        if (response.data && response.data['subsonic-response'] && response.data['subsonic-response'].status === 'failed') {
            const error = response.data['subsonic-response'].error;
            console.error(`Navidrome Plugin: API Error - Code ${error.code}: ${error.message}`);
            throw new Error(`Navidrome API 错误: ${error.message} (代码: ${error.code})`);
        }
        if (response.status < 200 || response.status >= 300) {
             console.error(`Navidrome Plugin: HTTP Error - Status ${response.status}`);
             throw new Error(`Navidrome 服务器请求失败，HTTP 状态码: ${response.status}`);
        }
        return response.data;
    } catch (error) {
        console.error(`Navidrome Plugin: Failed to fetch ${fullUrl}. Error:`, error);
         if (error instanceof Error && error.message.startsWith('Navidrome')) throw error;
         else throw new Error(`无法连接到 Navidrome 服务器或请求失败: ${error.message}`);
    }
}

// --- Data Formatting Functions ---
function formatMusicItem(navidromeSong) {
    return {
        id: String(navidromeSong.id), title: navidromeSong.title || "未知歌曲",
        artist: navidromeSong.artist || "未知艺术家", album: navidromeSong.album || "未知专辑",
        artwork: navidromeSong.coverArt, duration: navidromeSong.duration,
    };
}
function formatAlbumItem(navidromeAlbum) {
    return {
        id: String(navidromeAlbum.id), title: navidromeAlbum.name || navidromeAlbum.title || "未知专辑",
        artist: navidromeAlbum.artist || "未知艺术家", artwork: navidromeAlbum.coverArt,
        description: `歌曲数: ${navidromeAlbum.songCount || '?'}`,
    };
}
function formatSheetItem(navidromePlaylist, username = "Navidrome 用户") {
    return {
        id: String(navidromePlaylist.id), title: navidromePlaylist.name || "未知播放列表",
        artist: navidromePlaylist.owner || username, artwork: navidromePlaylist.coverArt,
        description: `歌曲: ${navidromePlaylist.songCount || '?'}, 时长: ${Math.round((navidromePlaylist.duration || 0) / 60)}分钟`,
        playCount: navidromePlaylist.playCount,
    };
}

// --- API Interaction Functions ---

// Search Music/Album/Sheet
async function searchMusic(query, page) {
    const offset = (page - 1) * pageSize;
    console.log(`Navidrome Plugin: Searching Music - Query: "${query}", Page: ${page}`);
    const data = await httpGet('search3', { query, songCount: pageSize, songOffset: offset });
    const songs = data?.['subsonic-response']?.searchResult3?.song ?? [];
    console.log(`Navidrome Plugin: searchMusic found ${songs.length} songs for page ${page}`);
    return { isEnd: songs.length < pageSize, data: songs.map(formatMusicItem) };
}
async function searchAlbum(query, page) {
    const offset = (page - 1) * pageSize;
    console.log(`Navidrome Plugin: Searching Albums - Query: "${query}", Page: ${page}`);
    const data = await httpGet('search3', { query, albumCount: pageSize, albumOffset: offset });
    const albums = data?.['subsonic-response']?.searchResult3?.album ?? [];
     console.log(`Navidrome Plugin: searchAlbum found ${albums.length} albums for page ${page}`);
    return { isEnd: albums.length < pageSize, data: albums.map(formatAlbumItem) };
}
async function searchSheet(query, page, username) {
    console.log(`Navidrome Plugin: Searching Sheets - Query: "${query}", Page: ${page} (page ignored)`);
    const data = await httpGet('getPlaylists', {});
    const playlists = data?.['subsonic-response']?.playlists?.playlist ?? [];
    console.log(`Navidrome Plugin: Received ${playlists.length} total playlists for search.`);
    let filteredPlaylists = playlists;
    if (query && query.trim()) {
        const lowerCaseQuery = query.trim().toLowerCase();
        filteredPlaylists = playlists.filter(p => p.name && p.name.toLowerCase().includes(lowerCaseQuery));
        console.log(`Navidrome Plugin: Filtered to ${filteredPlaylists.length} playlists matching "${query}"`);
    }
    return { isEnd: true, data: filteredPlaylists.map(p => formatSheetItem(p, username)) };
}

// Get Album Info (No change needed)
async function getAlbumInfoApi(albumItem, page) {
    console.log(`Navidrome Plugin: Fetching songs for Album ID: ${albumItem.id}, Page: ${page}`);
     if (page > 1) { return { isEnd: true, musicList: [] }; }
    const data = await httpGet('getAlbum', { id: albumItem.id });
    const albumData = data?.['subsonic-response']?.album;
    const songs = albumData?.song ?? [];
     console.log(`Navidrome Plugin: Found ${songs.length} songs in album ${albumItem.id}`);
     const supplementaryAlbumData = formatAlbumItem(albumData || { id: albumItem.id, title: albumItem.title });
     if (albumData?.artist && albumData?.year) supplementaryAlbumData.description = `${albumData.artist} - ${albumData.year}`;
     else if (albumData?.artist) supplementaryAlbumData.description = albumData.artist;
    return { isEnd: true, musicList: songs.map(formatMusicItem), albumItem: supplementaryAlbumData };
}


// --- Modified getMusicSheetInfoApi to handle BOTH playlists AND "All Songs" ---
async function getMusicSheetInfoApi(sheetItem, page) {

    // Check if it's the special "All Songs" sheet ID ***
    if (sheetItem.id === ALL_SONGS_TAG.id) {
        console.log(`Navidrome Plugin: Fetching ALL SONGS list, Page: ${page}`);
        // Call a new function designed to fetch all songs paginated
        return await getAllSongsApi(page);
    }

    // --- Original Playlist Logic ---
    console.log(`Navidrome Plugin: Fetching songs for REAL Playlist (Sheet) ID: ${sheetItem.id}, Page: ${page}`);
    if (page > 1) { return { isEnd: true, musicList: [] }; }

    const data = await httpGet('getPlaylist', { id: sheetItem.id });
    const playlistData = data?.['subsonic-response']?.playlist;
    const songs = playlistData?.entry ?? [];
    console.log(`Navidrome Plugin: Found ${songs.length} songs in playlist ${sheetItem.id}`);
    const supplementarySheetData = formatSheetItem(playlistData || { id: sheetItem.id, name: sheetItem.title });
    if (playlistData?.comment) supplementarySheetData.description = playlistData.comment;

    return {
        isEnd: true,
        musicList: songs.map(formatMusicItem),
        sheetItem: supplementarySheetData
    };
}

// --- NEW Function to Fetch All Songs Paginated (using search3) ---
async function getAllSongsApi(page) {
    const offset = (page - 1) * pageSize;
    console.log(`Navidrome Plugin: Fetching all songs via search3, Page: ${page}, Offset: ${offset}`);

    try {
        // Use search3 with empty query (assuming this lists all songs - needs verification)
        const data = await httpGet('search3', {
            query: '',
            songCount: pageSize,
            songOffset: offset
        });

        const songs = data?.['subsonic-response']?.searchResult3?.song ?? [];
        console.log(`Navidrome Plugin: getAllSongsApi found ${songs.length} songs for page ${page}`);

        const isEnd = songs.length < pageSize;

        // This function is called by getMusicSheetInfo, which expects this return format
        return {
            isEnd: isEnd,
            musicList: songs.map(formatMusicItem),
            // We can provide minimal sheet info again for context on page 1
            sheetItem: page === 1 ? {
                id: ALL_SONGS_TAG.id,
                title: ALL_SONGS_TAG.title,
                description: "服务器上的全部音乐"
             } : undefined
        };
    } catch(e) {
        console.error(`Navidrome Plugin: Failed to fetch all songs (page ${page}) - ${e.message}`);
        // Return empty result in the expected format on error
        return { isEnd: true, musicList: [] };
    }
}


// Get Lyrics (Using /lyrics endpoint)
async function getLyricApi(musicItem) {
    console.log(`Navidrome Plugin: Attempting to fetch lyrics for Song: "${musicItem.title}" by ${musicItem.artist}`);
    if (!musicItem || !musicItem.title) { console.warn("Navidrome Plugin: Cannot fetch lyrics, missing music title."); return null; }
    const params = { title: musicItem.title };
    if (musicItem.artist && !['unknown artist', 'various artists'].includes(musicItem.artist.toLowerCase())) params.artist = musicItem.artist;
    if (musicItem.album && !['unknown album'].includes(musicItem.album.toLowerCase())) params.album = musicItem.album;
    console.log("Navidrome Plugin: Calling Lyrics API (/lyrics) with params:", params);
    try {
        const response = await axios_1.default.get(`${API_BASE_URL}/lyrics`, { params: params, responseType: 'text', timeout: 10000 });
        if (response.data && typeof response.data === 'string' && response.data.trim()) {
            if (response.data.toLowerCase().includes('not found') || response.data.length < 10) {
                 console.log(`Navidrome Plugin: Lyrics API (/lyrics) returned likely "not found" message for "${musicItem.title}"`);
            } else {
                 console.log(`Navidrome Plugin: Successfully found lyrics (plain text) for "${musicItem.title}"`);
                 return { rawLrc: response.data };
            }
        } else { console.log(`Navidrome Plugin: Lyrics API (/lyrics) returned empty or invalid data for "${musicItem.title}"`); }
    } catch (error) {
        if (error.response) console.error(`Navidrome Plugin: Lyrics API request failed for "${musicItem.title}". Status: ${error.response.status}, Data:`, error.response.data);
        else if (error.request) console.error(`Navidrome Plugin: Lyrics API request failed for "${musicItem.title}". No response received.`, error.request);
        else console.error(`Navidrome Plugin: Lyrics API request failed for "${musicItem.title}". Error:`, error.message);
    }
    return null;
}


// --- Modified Recommended Sheets Tags API ---
async function getRecommendSheetTagsApi() {
  console.log("Navidrome Plugin: Providing tags for recommended sheets (Playlists & All Songs).");
  // Return BOTH tags, pinned for easy access
  return {
    pinned: [
        ALL_SONGS_TAG,
        ALL_PLAYLISTS_TAG
    ],
    data: []
  };
}

// --- Modified Recommended Sheets By Tag API ---
async function getRecommendSheetsByTagApi(tag, page, username) {
  console.log(`Navidrome Plugin: Getting recommended sheets for tag: ${tag.title} (ID: ${tag.id}), Page: ${page}`);

  // --- Handle Playlist Tag ---
  if (tag.id === ALL_PLAYLISTS_TAG.id) {
      console.log("Navidrome Plugin: Requesting playlists for '在线歌单' tag.");
      // Ignore page for playlists, fetch all
      if (page > 1) return { isEnd: true, data: [] };

      const data = await httpGet('getPlaylists', {});
      const playlists = data?.['subsonic-response']?.playlists?.playlist ?? [];
      console.log(`Navidrome Plugin: Found ${playlists.length} playlists.`);
      return { isEnd: true, data: playlists.map(p => formatSheetItem(p, username)) };
  }
  // --- Handle "All Songs" Tag ---
  else if (tag.id === ALL_SONGS_TAG.id) {
      console.log("Navidrome Plugin: Requesting the 'All Songs' fake sheet entry.");
      // This tag only returns one "sheet" (the entry point), so ignore page > 1
      if (page > 1) return { isEnd: true, data: [] };

      // Create and return the single fake sheet item
      const fakeSheet = {
          id: ALL_SONGS_TAG.id,
          title: ALL_SONGS_TAG.title,
          artist: username || "Navidrome",
          artwork: null,
          description: "浏览服务器上的所有歌曲"
      };
      return {
          isEnd: true,
          data: [fakeSheet]
      };
  }
  // --- Handle Unexpected Tag ---
  else {
      console.warn(`Navidrome Plugin: Received unexpected tag ID in getRecommendSheetsByTag: ${tag.id}`);
      return { isEnd: true, data: [] };
  }
}

// Get Stream URL (No change needed)
async function getMediaSourceApi(musicItem, quality) {
    var _a;
    console.log(`Navidrome Plugin: Getting media source for Song ID: ${musicItem.id} (Quality: ${quality})`);
    const userVariables = (_a = env === null || env === void 0 ? void 0 : env.getUserVariables()) !== null && _a !== void 0 ? _a : {};
    let { url, username, password } = userVariables;
    if (!(url && username && password)) { console.error("Navidrome Plugin: Missing credentials for getMediaSource."); return null; }
    if (!url.startsWith("http://") && !url.startsWith("https://")) url = `http://${url}`;
     url = url.replace(/\/+$/, "");
    const salt = Math.random().toString(16).slice(2);
    const token = CryptoJs.MD5(`${password}${salt}`).toString(CryptoJs.enc.Hex);
    const streamUrl = new URL(`${url}/rest/stream`);
    streamUrl.searchParams.append('u', username);
    streamUrl.searchParams.append('s', salt);
    streamUrl.searchParams.append('t', token);
    streamUrl.searchParams.append('c', 'MusicFree');
    streamUrl.searchParams.append('v', '1.16.1');
    streamUrl.searchParams.append('id', String(musicItem.id));
    const finalUrl = streamUrl.toString();
    console.log(`Navidrome Plugin: Generated stream URL: ${finalUrl}`);
    return { url: finalUrl };
}

// Get Music Info for Cover Art (No change needed)
async function getMusicInfoApi(musicItem) {
    console.log(`Navidrome Plugin: Constructing cover URL for ID: ${musicItem.id} Title: ${musicItem.title}`);
    if (!musicItem || !musicItem.title) {
        console.warn("Navidrome Plugin: Cannot construct cover URL, missing title.");
        return null;
    }
    try {
        const params = new URLSearchParams();
        params.append('title', musicItem.title);
        if (musicItem.artist && !['unknown artist', 'various artists'].includes(musicItem.artist.toLowerCase())) params.append('artist', musicItem.artist);
        if (musicItem.album && !['unknown album'].includes(musicItem.album.toLowerCase())) params.append('album', musicItem.album);
        const coverApiUrl = `${API_BASE_URL}/cover?${params.toString()}`;
        console.log(`Navidrome Plugin: Constructed cover URL: ${coverApiUrl}`);
        return { artwork: coverApiUrl };
    } catch (e) {
        console.error(`Navidrome Plugin: Failed to construct cover URL in getMusicInfoApi - ${e.message}`);
        return null;
    }
}


// --- MusicFree Plugin Definition ---

module.exports = {
    platform: "未响",
    version: "1.6.0",
    author: '猫头猫 & AI Assistant',
    srcUrl: "",
    cacheControl: "no-cache",

    // User Variables
    userVariables: [
        { key: "url", name: "服务器地址 (URL)", desc: "例如: http://192.168.1.100:4533" },
        { key: "username", name: "用户名" },
        { key: "password", name: "密码", type: 'password' },
    ],

    // Supported Search Types
    supportedSearchType: ["music", "album", "sheet"],

    // --- Exported Functions ---

    // Search Function
    async search(query, page, type) {
        console.log(`Navidrome Plugin: EXPORTED search called - Type: "${type}", Query: "${query}", Page: ${page}`);
        const userVariables = env?.getUserVariables() ?? {};
        try {
            if (type === "music") return await searchMusic(query, page);
            if (type === "album") return await searchAlbum(query, page);
            if (type === "sheet") return await searchSheet(query, page, userVariables.username);
            console.warn(`Navidrome Plugin: Unsupported search type "${type}" in exported search`);
            return { isEnd: true, data: [] };
        } catch (e) { console.error(`Navidrome Plugin: Exported search failed - ${e.message}`); return { isEnd: true, data: [] }; }
    },

    // Get Album Details
    async getAlbumInfo(albumItem, page) {
        console.log(`Navidrome Plugin: EXPORTED getAlbumInfo called - ID: ${albumItem.id}, Page: ${page}`);
         try { return await getAlbumInfoApi(albumItem, page); }
         catch (e) { console.error(`Navidrome Plugin: Exported getAlbumInfo failed - ${e.message}`); return { isEnd: true, musicList: [] }; }
    },

    // Get Music Sheet (Playlist OR All Songs) Details
     async getMusicSheetInfo(sheetItem, page) {
         console.log(`Navidrome Plugin: EXPORTED getMusicSheetInfo called - ID: ${sheetItem.id}, Title: ${sheetItem.title}, Page: ${page}`);
         // This function now routes internally based on sheetItem.id
         try { return await getMusicSheetInfoApi(sheetItem, page); }
         catch (e) { console.error(`Navidrome Plugin: Exported getMusicSheetInfo failed - ${e.message}`); return { isEnd: true, musicList: [] }; }
    },

    // Get Stream URL
    async getMediaSource(musicItem, quality) {
        console.log(`Navidrome Plugin: EXPORTED getMediaSource called - ID: ${musicItem.id}, Quality: ${quality}`);
        try { return await getMediaSourceApi(musicItem, quality); }
        catch (e) { console.error(`Navidrome Plugin: Exported getMediaSource failed - ${e.message}`); return null; }
    },

    // Get Lyrics
    async getLyric(musicItem) {
        console.log(`Navidrome Plugin: EXPORTED getLyric called - ID: ${musicItem.id}`);
        try { return await getLyricApi(musicItem); }
        catch (e) { console.error(`Navidrome Plugin: Exported getLyric failed - ${e.message}`); return null; }
    },

    // Get Recommended Sheet Tags (Playlists & All Songs)
    async getRecommendSheetTags() {
        console.log("Navidrome Plugin: EXPORTED getRecommendSheetTags called");
        try { return await getRecommendSheetTagsApi(); }
        catch (e) { console.error(`Navidrome Plugin: Exported getRecommendSheetTags failed - ${e.message}`); return { pinned: [], data: [] }; }
    },

    // Get Recommended Sheets By Tag (Handles Playlists & the "All Songs" entry)
    async getRecommendSheetsByTag(tag, page) {
        console.log(`Navidrome Plugin: EXPORTED getRecommendSheetsByTag called - Tag: ${tag.title}, Page: ${page}`);
         const userVariables = env?.getUserVariables() ?? {};
         try { return await getRecommendSheetsByTagApi(tag, page, userVariables.username); }
         catch (e) { console.error(`Navidrome Plugin: Exported getRecommendSheetsByTag failed - ${e.message}`); return { isEnd: true, data: [] }; }
    },

    // Get Music Info (for Cover Art)
    async getMusicInfo(musicItem) {
        console.log(`Navidrome Plugin: EXPORTED getMusicInfo called - ID: ${musicItem.id} Title: ${musicItem.title}`);
        try { return await getMusicInfoApi(musicItem); }
        catch (e) { console.error(`Navidrome Plugin: Exported getMusicInfo failed - ${e.message}`); return null; }
    }
};